import doctest

class Evaluator:
    def evaluate(self, expected, actual):
        pass

class SimpleEvaluator(Evaluator):
    def evaluate(self, expected, actual):
        '''
        >>> evaluator = SimpleEvaluator()
        >>> evaluator.evaluate((2, ), (1, ))
        0.5
        >>> evaluator.evaluate((2, ), (2, ))
        1.0
        >>> evaluator.evaluate((2, ), (4, ))
        0.5
        >>> evaluator.evaluate((0, ), (1, ))
        0.0
        >>> evaluator.evaluate((0, ), (0, ))
        1.0
        
        should return (1 / 2 + 2 / 4) / 2 = 0.5
        >>> evaluator.evaluate((2, 2), (1, 4))
        0.5
        
        should only use the first element in actual
        because the expected has only one element
        >>> evaluator.evaluate((2, ), (2, 4))
        1.0
        '''
        ratios = [self.calc_ratio(expected[i], actual[i])
                  for i in range(len(expected))]
        fitness = sum(ratios) / len(expected)
        return fitness
    
    def calc_ratio(self, expected, actual):
        '''
        >>> evaluator = SimpleEvaluator()
        
        should return 1 / 2 = 0.5
        >>> evaluator.calc_ratio(2, 1)
        0.5
        
        should return 2 / 2 = 1.0
        >>> evaluator.calc_ratio(2, 2)
        1.0
        
        should return 2 / 4 = 0.5
        >>> evaluator.calc_ratio(2, 4)
        0.5
        
        should return 0 because the dividor is 0
        >>> evaluator.calc_ratio(0, 2)
        0.0
        
        should return 1 because it is perfectly fit
        >>> evaluator.calc_ratio(0, 0)
        1.0
        '''
        if expected == 0:
            return 1.0 if actual == 0 else 0.0
        else:
            return float(actual) / expected if actual < expected else float(expected) / actual

if __name__ == '__main__':
    doctest.testmod()